Thoughts on the "object-level" interface


1)  Volumes

An object-id is volume-specific (and there isn't enough spare space to hold a
reasonably sized "drive number") so objects will need to be specified by
pairs of values:

   vol-ref         (32 bits)
   object-id       (32 bits)

I haven't yet thought about an interface for vol-ref's.



2)  Naming convention

Each function name starts NC_object_...



3)  Types

  typedef int VolRef;

  typedef int ObjectID;

  enum {                      /* possible allocation strategies */
    STRATEGY_FILE,
    STRATEGY_DIR
  } Strategy;

  typedef short ZoneID;       /* only 16 bits needed */

  typedef int ObjHandle;



4)  Miscellaneous functions


  ZoneID NC_object_home_zone
  (
    ObjectID object_id
  );

    /* Returns the zone-id for the zone in which the object is situated;
       probably a macro.
    */



5)  Operations on unopened objects


  ObjectID NC_object_create
  (
    VolRef vol_ref,
    Strategy strategy,
    int *size,
    ZoneID parent_zone,
    ZoneID (*sibling_zone_func)(void *h, int *n),
    void *handle
  );

    /* Allocates space for a new object, using the indicated strategy.

       At least *size bytes will be allocated; on exit, this parameter is
       updated with the actual amount of space allocated to the object.

       The result is the object-id of the new object.

       The use of the remaining parameters depends on the strategy chosen:

        strategy = STRATEGY_FILE:

         This is the allocation strategy used for creating new files; the
         parent_zone identifies the zone in which the file's parent 
         directory is situated, and sibling_zone_func is a function which
         can be called to supply a list of zones to which other files in
         that directory have been allocated, eg:

            zone-list = sibling_zone_func(handle, &n)

         If the result is NULL, *n = 0, and there are no more sibling
         zones; otherwise, zone-list addresses an array of *n zone-id's.

        strategy = STRATEGY_DIR:

         This is the allocation strategy used for creating new directories.
         parent_zone identifies the zone in which the directory's parent
         directory is situated, and the other two parameters are ignored.
    */


  void NC_object_delete
  (
    VolRef vol_ref,
    ObjectID object_id
  );

    /* Deletes an object; error if object is open.
    */



6)  Operations on open objects


  ObjHandle NC_object_open
  (
    VolRef vol_ref,
    ObjectID object_id
  );

    /* Open an object */


  void NC_object_read
  (
    ObjHandle handle,
    int address,
    char *buffer,
    int n
  );

    /* Read n bytes starting at address into buffer */


  void NC_object_write
  (
    ObjHandle handle,
    int address,
    char *buffer,
    int n
  );

    /* Write n bytes to address from buffer */


  void NC_object_bkg_read
  (
    ObjHandle handle,
    int address,
    char *buffer,
    int n,
    void (*completed)(void* handle),
    void *handle
  );

    /* Background read - completed(handle) is called when all is done */


  void NC_object_bkg_write
  (
    ObjHandle handle,
    int address,
    char *buffer,
    int n,
    void (*completed)(void* handle),
    void *handle
  );

    /* Background write - completed(handle) is called when all is done */


  int NC_object_size
  (
    ObjHandle handle
  );

    /* returns amount of space allocated to the object */


  ObjectID NC_object_reallocate
  (
    ObjHandle handle,
    Strategy strategy,
    int *size,
    ZoneID parent_zone,
    ZoneID (*sibling_zone_func)(void *h, int *n),
    void *handle
  );

    /* Called to extend or truncate an object.

       For parameter details, see NC_object_create.

       The result is the object's new object-id - which may be different from
       its previous id.
    */


  void NC_object_close
  (
    ObjHandle handle
  );

    /* Close an object */


Notes:

It is up to higher-level software to ensure that reads/writes lie within the
object, that access controls are enforced, and to maintain any file pointers:
this level knows nothing about the internal structure of objects.

However, this level *does* know the difference between open and closed
objects, and so will fault attempts to delete an object that is open, for
example.

What about interaction between background transfers and requests to close or
reallocate an object?


